using System;
using System.Collections.Generic;
using System.Threading;

namespace SBPweb.Logging
{
    public static partial class LogManager
    {
        private static Dictionary<int, Dictionary<String, int>> mKeywords = new Dictionary<int, Dictionary<string, int>>();  // Thread - keyword pairs

        /// <summary>
        /// Add a new set of keywords to the thread specific set.
        /// </summary>
        /// <param name="Keywords">Set of keywords to add.</param>
        /// <remarks>
        /// This method is thread safe.
        /// This method supports the EntLib infrastructure.
        /// </remarks>
        /// <example>
        /// The following example demonstrates the adequat way of keyword definition.
        /// <code>
        /// using (new Keyword(new string [] {"Keyword_1", "Keyword_2"}))
        /// {
        ///     using (new Keyword("Keyword_3")
        ///     {
        ///         LogManager.WriteCritical("Message");
        ///     }
        /// }
        /// </code>
        /// </example>
        internal static void AddKeywords(ICollection<String> Keywords)
        {
            lock (mKeywords)
            {
                if (!mInitialized)
                    return;

                Dictionary<String, int> keywords;

                if (!mKeywords.TryGetValue(Thread.CurrentThread.ManagedThreadId, out keywords))
                    keywords = mKeywords[Thread.CurrentThread.ManagedThreadId] = new Dictionary<string, int>();

                int refcount = 0;

                foreach (String keyword in Keywords)
                {
                    keywords[keyword] = keywords.TryGetValue(keyword, out refcount) ? refcount + 1 : 1;
                }
            }
        }

        /// <summary>
        /// Removes a new set of keywords from the thread specific set.
        /// </summary>
        /// <param name="Keywords">Set of keywords to remove.</param>
        /// <remarks>
        /// This method is thread safe.
        /// This method supports the EntLib infrastructure.
        /// </remarks>
        /// <example>
        /// The following example demonstrates the adequat way of keyword definition.
        /// <code>
        /// using (new Keyword(new string [] {"Keyword_1", "Keyword_2"}))
        /// {
        ///     using (new Keyword("Keyword_3")
        ///     {
        ///         LogManager.WriteCritical("Message");
        ///     }
        /// }
        /// </code>
        /// </example>
        internal static void RemoveKeywords(ICollection<String> Keywords)
        {
            lock (mKeywords)
            {
                if (!mInitialized)
                    return;

                Dictionary<String, int> keywords;

                try
                {
                    keywords = mKeywords[Thread.CurrentThread.ManagedThreadId];
                }
                catch (KeyNotFoundException)
                {
                    // May not really happen
                    return;
                }

                List<String> removeable = new List<string>(keywords.Count);
                int refcount;

                foreach (String keyword in Keywords)
                {
                    try
                    {
                        if ((refcount = keywords[keyword]) == 1)
                            removeable.Add(keyword);
                        else
                            keywords[keyword] = refcount - 1;
                    }
                    catch (KeyNotFoundException)
                    {
                        // May not really happen
                    }
                }

                foreach (String keyword in removeable)
                    keywords.Remove(keyword);

                removeable.Clear();

                if (keywords.Count == 0)
                {
                    lock (mKeywords)
                    {
                        mKeywords.Remove(Thread.CurrentThread.ManagedThreadId);
                    }
                }
            }
        }
    }
}